﻿
using Xacml.Core;
using Xacml.Core.Interfaces;
using Xacml.Core.Runtime;
using Xacml.Core.Runtime.Functions;
using System;
using System.Globalization;
using System.Text.RegularExpressions;

namespace Xacml.Core.Runtime.DataTypes
{
  public class YearMonthDuration : IDataType
  {
    private const string PATTERN = "[\\-]?P[0-9]+(Y([0-9]+M)?|M)";
    private const string PATTERN_MATCH = "(?<n>[\\-]?)P((?<y>\\d+)Y)?((?<m>\\d+)M)?";
    private string _durationValue;
    private int _years;
    private int _months;
    private bool _negative;

    public int Years
    {
      get
      {
        if (!this._negative)
          return this._years;
        return this._years * -1;
      }
    }

    public int Months
    {
      get
      {
        if (!this._negative)
          return this._months;
        return this._months * -1;
      }
    }

    public IFunction EqualFunction
    {
      get
      {
        return (IFunction) new YearMonthDurationEqual();
      }
    }

    public IFunction IsInFunction
    {
      get
      {
        return (IFunction) new YearMonthDurationIsIn();
      }
    }

    public IFunction SubsetFunction
    {
      get
      {
        return (IFunction) new YearMonthDurationSubset();
      }
    }

    public string DataTypeName
    {
      get
      {
        return "http://www.w3.org/TR/2002/WD-xquery-operators-20020816#yearMonthDuration";
      }
    }

    internal YearMonthDuration()
    {
    }

    public YearMonthDuration(string value)
    {
      this._durationValue = value;
      if (new Regex("[\\-]?P[0-9]+(Y([0-9]+M)?|M)").Match(value).Success)
      {
        Match match = new Regex("(?<n>[\\-]?)P((?<y>\\d+)Y)?((?<m>\\d+)M)?").Match(value);
        if (!match.Success)
          throw new EvaluationException(Resource.ResourceManager[Resource.MessageKey.exc_bug]);
        this._negative = match.Groups["n"].Value == "-";
        this._years = int.Parse(match.Groups["y"].Value, (IFormatProvider) CultureInfo.InvariantCulture);
        this._months = int.Parse(match.Groups["m"].Value, (IFormatProvider) CultureInfo.InvariantCulture);
      }
      else
        throw new EvaluationException(Resource.ResourceManager[Resource.MessageKey.exc_invalid_yearmonth_duration_value, new object[1]
        {
          (object) value
        }]);
    }

    public override int GetHashCode()
    {
      return base.GetHashCode();
    }

    public override bool Equals(object obj)
    {
      if (!(obj is YearMonthDuration))
        return base.Equals(obj);
      YearMonthDuration yearMonthDuration = (YearMonthDuration) obj;
      if (this._months == yearMonthDuration._months && this._years == yearMonthDuration._years)
        return this._negative == yearMonthDuration._negative;
      return false;
    }
  }
}
